package ar.edu.uba.fi.jmit.aspecter.monitor.objectCount;

import java.util.Date;
import java.util.List;

import javassist.ClassPool;
import javassist.CtClass;
import ar.edu.uba.fi.jmit.aspecter.AspecterTestCase;
import ar.edu.uba.fi.jmit.aspecter.core.Constants;
import ar.edu.uba.fi.jmit.aspecter.core.ResourceProperties;
import ar.edu.uba.fi.jmit.aspecter.core.interceptor.Interceptor;
import ar.edu.uba.fi.jmit.aspecter.monitor.testUtils.EventPriorityMock;
import ar.edu.uba.fi.jmit.aspecter.monitor.testUtils.MockEvent;
import ar.edu.uba.fi.jmit.aspecter.monitor.testUtils.MonitorTarget;
import ar.edu.uba.fi.jmit.aspecter.monitor.testUtils.SenderFactoryMock;

public class ObjectCountNewInstanceInterceptorTestCase extends AspecterTestCase {

	@SuppressWarnings("unchecked")
	public void testObjectCount() {
		SenderFactoryMock.clean();
		try {
			Interceptor interceptor = new ObjectCountNewInstanceInterceptor("ar.edu.uba.fi.jmit.aspecter.monitor.testUtils.MonitorTarget", "ObjectCountNewInstanceInterceptorTestCase_test1");
			CtClass ctClass = ClassPool.getDefault().getAndRename("ar.edu.uba.fi.jmit.aspecter.monitor.testUtils.ObjectCountTargetObject", getNextClassName());
			ctClass.instrument(interceptor);
			Class<?> clazz = ctClass.toClass();
			Object target = clazz.newInstance();
			clazz.getMethod("createMonitorTarget").invoke(target);
			List<MonitorTarget> createdObjects = (List<MonitorTarget>) clazz.getMethod("getCreatedMonitorTargets").invoke(target);
			assertEquals(SenderFactoryMock.getSenderInstance().getSendedEvents().size(), createdObjects.size());
			assertEquals(1, SenderFactoryMock.getSenderInstance().getSendedEvents().size());
			
			clazz.getMethod("createNMonitorTarget", int.class).invoke(target, 9);
			assertEquals(SenderFactoryMock.getSenderInstance().getSendedEvents().size(), createdObjects.size());
			assertEquals(10, SenderFactoryMock.getSenderInstance().getSendedEvents().size());
			
			Object target2 = clazz.newInstance();
			clazz.getMethod("createNMonitorTarget", int.class).invoke(target2, 10);

			assertEquals(20, SenderFactoryMock.getSenderInstance().getSendedEvents().size());
			assertEquals(10, createdObjects.size());
			assertEquals(10, ((List<MonitorTarget>) clazz.getMethod("getCreatedMonitorTargets").invoke(target2)).size());
		} catch (Exception e) {
			fail(e);
		} 
	}
	
	public void testSendedData() {
		SenderFactoryMock.clean();
		try {
			Interceptor interceptor = new ObjectCountNewInstanceInterceptor("ar.edu.uba.fi.jmit.aspecter.monitor.testUtils.MonitorTarget", "ObjectCountNewInstanceInterceptorTestCase_test2");
			CtClass ctClass = ClassPool.getDefault().getAndRename("ar.edu.uba.fi.jmit.aspecter.monitor.testUtils.ObjectCountTargetObject", getNextClassName());
			ctClass.instrument(interceptor);
			Class<?> clazz = ctClass.toClass();
			Object target = clazz.newInstance();
			clazz.getMethod("createMonitorTarget").invoke(target);
			List<MockEvent> list = SenderFactoryMock.getSenderInstance().getSendedEvents();
			assertEquals(1, list.size());
			MockEvent event = list.get(0);
			assertEquals("ObjectCountNewInstanceInterceptorTestCase_test2", event.getData().get(ResourceProperties.getProperty(Constants.EVENT_MONITOR_NAME_KEY)));
			Date eventDate = (Date) event.getData().get(ResourceProperties.getProperty(Constants.EVENT_MONITOR_DATE));
			assertSimilarDates(new Date(), eventDate);
			assertEquals(event.getSource(), "ar.edu.uba.fi.jmit.aspecter.monitor.testUtils.MonitorTarget");
			assertEquals(EventPriorityMock.NORMAL, event.getPriority());
		} catch (Exception e) {
			fail(e);
		}
	}
	
	public void testEventPriority() {
		SenderFactoryMock.clean();
		try {
			Interceptor interceptor = new ObjectCountNewInstanceInterceptor("ar.edu.uba.fi.jmit.aspecter.monitor.testUtils.MonitorTarget", "ObjectCountNewInstanceInterceptorTestCase_test2", "ALERT");
			CtClass ctClass = ClassPool.getDefault().getAndRename("ar.edu.uba.fi.jmit.aspecter.monitor.testUtils.ObjectCountTargetObject", getNextClassName());
			ctClass.instrument(interceptor);
			Class<?> clazz = ctClass.toClass();
			Object target = clazz.newInstance();
			clazz.getMethod("createMonitorTarget").invoke(target);
			assertEquals(0, SenderFactoryMock.getSenderInstance().getSendedEvents().size());
			List<MockEvent> list = SenderFactoryMock.getSenderInstance().getHpSendedEvents();
			assertEquals(1, list.size());
			MockEvent event = list.get(0);
			assertEquals(EventPriorityMock.ALERT, event.getPriority());
		} catch (Exception e) {
			fail(e);
		}
	}
}
